library(tidyverse)
library(glue)
library(scales)
library(gt)
library(ggiraph) # interactive plots
library(tidycensus)
library(tigris) # TIGER/Line shapefiles
library(sf) # simple features for spatial analysisCleveland’s Changing Population
Exploring the US Census with R
The resurgence of people moving to downtown Cleveland is making news.1 According to a study commissioned by Downtown Cleveland Inc., the downtown population was almost 19,000 in the 2020 census, a 22% increase from 2010.2 However, Cleveland Open Data shows only 13,0003. Cleveland Scene reports that there are lots of estimates out there, one as low as 8,000!4 What gives? The organizations may be using different sources, like the decennial US census vs the more recent, but less comprehensive, American Community Survey. But it seems more likely they are using different geographic boundaries.
I was able to reproduce some estimates. My main tools to do this was the tidycensus R package, and the Cleveland Open Data service. I’ve stepped through the process below.
This web page is a working file. It’s mostly a toy project to learn cool R package, learn how to retrieve data from the US Census Bureau API, and leave a record I can refer to later. If you are reading this and are not me, I hope this helps with whatever you’re doing. Otherwise, ‘hello, future me!’ You can find the source code and downloaded data on my GitHub page.
Defining “Downtown”
Cleveland extends from Cleveland Hopkins Airport on the west all the way to Euclid on the east. It’s mostly bounded on the south by I-80. Here is the map from the Cleveland Wikipedia Page.
The 2020 US decennial census counted 372K people in Cleveland.5 That’s a decline from 397K in 2010. The 1-year American Community Survey (ACS) shows it is still falling, down to 363K in 2023.6 But the decline is uneven, and parts of the city are actually growing, including the downtown area. There is no official definition of downtown, so we can make some choices. The Census Bureau provides the building blocks for a definition: over 15K census blocks in Cleveland, rolled up to around 200 census tracts.
The Cleveland City Planning Commission (CPC) defines 34 neighborhoods in Cleveland for urban planning initiatives.7 They are also called Statistical (or Social) Planning Areas (SPAs). There is a pdf map at the CPC that I copy/pasted below. You can see from the map that there is a neighborhood actually called “Downtown”. It’s the area bounded by the Cuyahoga and I-90. Cleveland Open Data has an interactive map that you can explore and download. I followed the link above and downloaded and extracted the shapefile.
So that is one definition. A second one comes from a study by Urban Partners that was commission by Downtown Cleveland, Inc. in 2023. Page 3 of the pdf report (copy/pasted below) shows a Westside and a Downtown Core. Whereas the Downtown neighborhood had about 13.3K people in the 2020 census, this definition has 18.7K in the Downtown Core. The main differences are that Urban Partners took a bite out of the Central neighborhood on the east side, and parts of the West Bank of the Flats in the Cuyahoga Valley and Ohio City neighborhoods.
Blocks, Tracts, and Subdivisions
Several libraries make it easy to work with census data. The tidycencus package was developed to interface with the US Census Bureau APIs. It also returns feature geometries for spatial analysis. The tigris package works with the Census Bureau’s TIGER/Line shapefiles, and the sf (simple features) package performs spatial operations.
The first step is to get the CPC’s definition of neighborhoods. I used the City of Cleveland Open Data web site’s interactive analysis of the 2020 US Census.8 The map has five layers (screen capture below). The first is the shape file of the 34 neighborhoods. The second contains population data from the 2020 decennial census complete with census block, census tract, and SPA name. I downloaded and unzipped the first two files.
# Nice contiguous shape file. One record for each of the 34 SPAs.
cleve_neigh_0 <-
st_read(file.path(
"inputs/Cleveland Neighborhoods",
"Neighborhood_Population_Change.shp"
))
# Cleveland populated blocks. Includes block, tract, and SPA name.
cleve_blocks <- st_read(file.path(
"inputs/Cleveland Populated Blocks 2020",
"Decennial_2020_Populated_Blocks_Cleveland_Only.shp"
)) |>
select(-starts_with("P0"), -starts_with("H0"))You can join cleve_neigh_0 to US Census Bureau data files with the tigris package to roll up block-level data into SPAs. In fact, that’s what I’ll do for the 2000 and 2010 censuses, but it’s not perfectly accurate, so that’s why I grabbed that second file.
Next, I loaded some shapefiles from the tigris package to facilitate mapping.
oh_state <- tigris::states(cb = TRUE) |> filter(STUSPS == "OH")
oh_counties <- tigris::counties(cb = TRUE) |> filter(STUSPS == "OH")
cuya_county <- oh_counties |> filter(NAME == "Cuyahoga")
oh_places <- tigris::places("OH", year = 2022)
x <- c("Euclid", "Parma", "North Olmsted", "Shaker Heights", "Solon", "Lakewood")
my_places <- oh_places |> filter(NAME %in% x) |> st_centroid()
terminal_tower <- st_sfc(st_point(c(-81.69387, 41.49824)), crs = 4326)Here is a plot of Cuyahoga County, Cleveland, and the 34 Cleveland neighborhoods. Hover over the shapes to see their names. There’s Terminal Tower in the heart of downtown. I marked some neighboring cities to get a sense of the geography.
Show the code
p <-
ggplot() +
geom_sf(data = oh_state, color = "gray60") +
geom_sf_interactive(
data = oh_counties,
aes(tooltip = NAME),
fill = "honeydew", color = "gray90"
) +
geom_sf(data = cuya_county, fill = "honeydew2", color = "gray80") +
geom_sf_interactive(
data = cleve_neigh_0,
aes(tooltip = SPA_NAME),
fill = "honeydew3", color = "honeydew4"
) +
geom_sf(data = my_places, color = "honeydew3") +
geom_sf(data = terminal_tower, color = "firebrick") +
geom_sf_text(data = terminal_tower, aes(label = "Terminal Tower"),
size = 3, hjust = .2, vjust = 1, color = "firebrick") +
geom_sf_text(data = my_places, aes(label = NAME), size = 3, hjust = .2, vjust = 1) +
coord_sf(xlim = c(-82.0, -81.3), ylim = c(41.25, 41.65)) +
theme(
panel.background = element_rect(fill = "skyblue"),
panel.grid = element_blank(),
axis.text = element_blank()
) +
labs(
x = NULL, y = NULL,
title = glue("Cleveland and Surrounding Cities, Cuyahoga County")
)
girafe(ggobj = p)Census Data
I don’t want to abuse the US Census Bureau API, so I’ll set a flag to only download data as I’m developing this script. Once I have what I want, I’ll keep my data on my local drive and build my report.
USE_API <- FALSEThe Census Bureau API allows you to select multiple variables from a single census file. There are a few files for each census, and the variable names change. I want the Cleveland area population in 2000, 2010, 2020, and the American Community Survey (ACS) 1-year estimate from 2023 (most recent). So despite the handiness of tidycensus package, data collection is still going to be a bit tedious.
The decennial census developer page lists the accessible datasets: 2000, 2010, and 2020. Before you do anything, you’ll need an API key from the Bureau. This is quick and easy: just click the “Request a KEY” tile in the menu at the left. The Census Bureau emails you a key. Best practice is to save the key in an .Renviron file.
usethis::edit_r_environ(scope = "project")This opens (or creates) a .Renviron file in your project root. Add your key. The name is important: CENSUS_API_KEY. The tidycensus functions send that system variable (if you don’t explicitly supply it in the function). Set it like this:
CENSUS_API_KEY="abc123"Now we’re ready to pull census data. I’ll start with 2020.
2020
Through trial and error, I discovered the Redistricting Data (PL 94-171) contains overall population. There is a full list of variables that represent the various sub-groups of the population. I used it and the tidycensus::load_variables() function to identify the ones I want. I’ll include race/ethnicity to investigate demographic trends.
pl_2020_vars <-
tidycensus::load_variables(2020, "pl") |>
filter(
between(name, "P2_001N", "P2_011N"),
!name %in% c("P2_003N", "P2_004N")
)Here they are after a bit of cleaning.
Show the code
pl_2020_vars <-
pl_2020_vars |>
mutate(
label = case_when(
str_detect(label, "White") ~ "White",
str_detect(label, "Black") ~ "Black",
str_detect(label, "Asian") ~ "Asian",
str_detect(label, "American Indian") ~ "American Indian",
str_detect(label, "Native Hawaiian") ~ "Pacific Islander",
str_detect(label, "Some Other Race") ~ "Other",
str_detect(label, "two or more races") ~ "Two or more races",
str_detect(label, "Hispanic") ~ "Hispanic",
str_detect(label, "Total") ~ "Total",
TRUE ~ label
),
rpt_group = if_else(name == "P2_001N", "Total", "Race/ethnicity"),
rpt_level = if_else(
label %in% c("White", "Black", "Hispanic", "Asian", "Total"),
label, "Other")
) |>
select(variable = name, label, rpt_group, rpt_level)
pl_2020_vars# A tibble: 9 × 4
variable label rpt_group rpt_level
<chr> <chr> <chr> <chr>
1 P2_001N Total Total Total
2 P2_002N Hispanic Race/ethnicity Hispanic
3 P2_005N White Race/ethnicity White
4 P2_006N Black Race/ethnicity Black
5 P2_007N American Indian Race/ethnicity Other
6 P2_008N Asian Race/ethnicity Asian
7 P2_009N Pacific Islander Race/ethnicity Other
8 P2_010N Other Race/ethnicity Other
9 P2_011N Two or more races Race/ethnicity Other
The Demographic Profile contains age counts, so I’ll grab that too since I am curious about general age patterns.
dp_2020_vars <-
tidycensus::load_variables(2020, "dp") |>
filter(
str_detect(label, "Count!!SEX AND AGE!!Total population"),
!str_detect(label, "Selected Age Categories"),
name != "DP1_0001C"
)Clean these too.
Show the code
dp_2020_vars <-
dp_2020_vars |>
mutate(
label = str_remove_all(label, "(Count!!SEX AND AGE!!Total population)|(!!)"),
label = if_else(label == "", "Total", label),
rpt_group = "Age",
rpt_level = case_when(
name <= "DP1_0004C" ~ "Under 15 yrs",
name <= "DP1_0006C" ~ "15 to 24 yrs",
name <= "DP1_0008C" ~ "25 to 34 yrs",
name <= "DP1_0010C" ~ "35 to 44 yrs",
name <= "DP1_0012C" ~ "45 to 54 yrs",
name <= "DP1_0014C" ~ "55 to 64 yrs",
TRUE ~ "65+ yrs"
)
) |>
select(variable = name, label, rpt_group, rpt_level)
dp_2020_vars# A tibble: 18 × 4
variable label rpt_group rpt_level
<chr> <chr> <chr> <chr>
1 DP1_0002C Under 5 years Age Under 15 yrs
2 DP1_0003C 5 to 9 years Age Under 15 yrs
3 DP1_0004C 10 to 14 years Age Under 15 yrs
4 DP1_0005C 15 to 19 years Age 15 to 24 yrs
5 DP1_0006C 20 to 24 years Age 15 to 24 yrs
6 DP1_0007C 25 to 29 years Age 25 to 34 yrs
7 DP1_0008C 30 to 34 years Age 25 to 34 yrs
8 DP1_0009C 35 to 39 years Age 35 to 44 yrs
9 DP1_0010C 40 to 44 years Age 35 to 44 yrs
10 DP1_0011C 45 to 49 years Age 45 to 54 yrs
11 DP1_0012C 50 to 54 years Age 45 to 54 yrs
12 DP1_0013C 55 to 59 years Age 55 to 64 yrs
13 DP1_0014C 60 to 64 years Age 55 to 64 yrs
14 DP1_0015C 65 to 69 years Age 65+ yrs
15 DP1_0016C 70 to 74 years Age 65+ yrs
16 DP1_0017C 75 to 79 years Age 65+ yrs
17 DP1_0018C 80 to 84 years Age 65+ yrs
18 DP1_0019C 85 years and over Age 65+ yrs
With the variable names in hand, we can request the data from the API. Cleveland is one of 59 subdivisions within Cuyahoga County. Counties are subdivided into census tracts, and census tracts are subdivided into census blocks. Cities often overlap census tracts, so I’ll defined Cleveland by joining to the cleve_blocks data I got from Cleveland Open Data.
Show the code
# Utility function to create factors
my_rpt_relevel <- function(x) {
ethn <- c("Black", "White", "Hispanic", "Asian", "Other", "Total")
x <- fct_relevel(x, ethn, after = Inf)
x <- fct_relevel(x, "Under 15 yrs", after = 0)
return(x)
}
# Urban Partners defn of Westside, uses tracts.
westside_tracts <- c(
"103100", "103400", "103500", "103602", "103800", "103900", "104100",
"104200", "104300", "197800", "197700", "197500", "104400"
)
# Urban Partners defn of Downtown Core, uses tracts and blocks
downtown_core_tracts_2020 <- c(
"103300", "107101", "107701", "107802", "109301")
downtown_core_blocks_2020 <- paste0(
"39035108701", c("2001", "2004", "2006", "2008"))
if (USE_API) {
subdiv_2020_pl <-
get_decennial(
geography = "county subdivision",
sumfile = "pl",
variables = pl_2020_vars$variable,
state = "OH",
county = "Cuyahoga",
geometry = TRUE,
year = 2020
) |>
inner_join(pl_2020_vars, by = "variable") |>
summarize(
.by = c(GEOID, NAME, geometry, rpt_group, rpt_level),
value = sum(value)
)
subdiv_2020_dp <-
get_decennial(
geography = "county subdivision",
sumfile = "dp",
variables = dp_2020_vars$variable,
state = "OH",
county = "Cuyahoga",
geometry = TRUE,
year = 2020
) |>
inner_join(dp_2020_vars, by = "variable") |>
summarize(
.by = c(GEOID, NAME, geometry, rpt_group, rpt_level),
value = sum(value)
)
tract_2020_pl <-
get_decennial(
geography = "tract",
sumfile = "pl",
variables = pl_2020_vars$variable,
state = "OH",
county = "Cuyahoga",
geometry = TRUE,
year = 2020
) |>
inner_join(pl_2020_vars, by = "variable") |>
summarize(
.by = c(GEOID, NAME, geometry, rpt_group, rpt_level),
value = sum(value)
)
tract_2020_dp <-
get_decennial(
geography = "tract",
sumfile = "dp",
variables = dp_2020_vars$variable,
state = "OH",
county = "Cuyahoga",
geometry = TRUE,
year = 2020
) |>
inner_join(dp_2020_vars, by = "variable") |>
summarize(
.by = c(GEOID, NAME, geometry, rpt_group, rpt_level),
value = sum(value)
)
block_2020_pl <-
get_decennial(
geography = "block",
sumfile = "pl",
variables = pl_2020_vars$variable,
state = "OH",
county = "Cuyahoga",
geometry = TRUE,
year = 2020
) |>
inner_join(pl_2020_vars, by = "variable") |>
summarize(
.by = c(GEOID, NAME, geometry, rpt_group, rpt_level),
value = sum(value)
)
# dp is not available at the block level
subdiv_2020 <-
bind_rows(subdiv_2020_pl, subdiv_2020_dp) |>
mutate(
rpt_level = my_rpt_relevel(rpt_level),
NAME = str_remove_all(NAME, "(, Cuyahoga County, Ohio)|(village)|(city)"),
NAME = str_trim(NAME)
)
tract_2020 <-
bind_rows(tract_2020_pl, tract_2020_dp) |>
mutate(rpt_level = my_rpt_relevel(rpt_level))
block_2020 <-
block_2020_pl |>
inner_join(
cleve_blocks |> as_tibble() |> select(GEOID20, SPA = SPA_NAME),
by = c("GEOID" = "GEOID20")
) |>
mutate(
rpt_level = my_rpt_relevel(rpt_level),
greater_downtown = case_when(
str_sub(GEOID, 6, 11) %in% westside_tracts ~ "Westside",
str_sub(GEOID, 6, 11) %in% downtown_core_tracts ~ "Downtown Core",
GEOID %in% downtown_core_blocks_2020 ~ "Downtown Core",
TRUE ~ "Other"
),
SPA = factor(str_to_title(SPA)),
SPA = fct_relevel(SPA, "Downtown", after = 0),
greater_downtown = factor(
greater_downtown, levels = c("Downtown Core", "Westside", "Other"))
)
save(
subdiv_2020, tract_2020, block_2020,
file = "decennial_2020.Rdata"
)
} else {
load("decennial_2020.Rdata")
}Cleveland’s population was 372,624 in 2020. The Downtown neighborhood had 13,302 people. The Downtown Core, which included a portion of the Central neighborhood, had 18,708 people.
| 2020 Population Estimates for Cleveland and Vicinity | |
|---|---|
| Population | |
| Cuyahoga County Subdivisions | |
| Cleveland | 372,624 |
| Other | 892,193 |
| Total | 1,264,817 |
| Cleveland Neighborhoods | |
| Downtown | 13,302 |
| Bellaire-Puritas | 13,823 |
| Broadway-Slavic Village | 19,022 |
| Brooklyn Centre | 8,315 |
| Buckeye Shaker | 11,419 |
| Central | 11,955 |
| Clark Fulton | 7,625 |
| Collinwood Nottingham | 9,616 |
| Cudell | 9,115 |
| Cuyahoga Valley | 1,293 |
| Detroit-Shoreway | 11,326 |
| Edgewater | 6,000 |
| Euclid Green | 5,051 |
| Fairfax | 5,167 |
| Glenville | 21,137 |
| Goodrich-Kirtland Park | 3,955 |
| Hopkins | 534 |
| Hough | 9,702 |
| Jefferson | 17,351 |
| Kamms Corners | 24,312 |
| Kinsman | 5,876 |
| Lee-Harvard | 9,770 |
| Lee-Seville | 4,171 |
| Mount Pleasant | 14,015 |
| North Shore Collinwood | 14,928 |
| Ohio City | 9,219 |
| Old Brooklyn | 32,315 |
| Saint Clair-Superior | 5,139 |
| Stockyards | 9,522 |
| Tremont | 7,798 |
| Union-Miles Park | 15,625 |
| University Circle | 9,620 |
| West Boulevard | 18,981 |
| Woodland Hills | 5,625 |
| Total | 372,624 |
| Greater Downtown | |
| Downtown Core | 18,708 |
| Westside | 18,407 |
| Other | 335,509 |
| Total | 372,624 |
2010
Unfortunately, getting 2010 and 2000 isn’t as simple as changing the year parameter in the API calls because they use a different file - Summary File 1.
sf1_2010_vars <-
tidycensus::load_variables(2010, "sf1") |>
filter(
concept %in% c("HISPANIC OR LATINO ORIGIN BY RACE", "SEX BY AGE"),
!name %in% c("P005002", "P012001", "P012002", "P012026"),
!str_detect(label, "Total!!Hispanic or Latino!!"),
!str_detect(name, "^PCT012")
)Show the code
sf1_2010_vars <-
sf1_2010_vars |>
mutate(
label = str_remove(label, "(Total!!Male!!)|(Total!!Female!!)"),
label = case_when(
str_detect(label, "White") ~ "White",
str_detect(label, "Black") ~ "Black",
str_detect(label, "Asian") ~ "Asian",
str_detect(label, "American Indian") ~ "American Indian",
str_detect(label, "Native Hawaiian") ~ "Pacific Islander",
str_detect(label, "Some Other Race") ~ "Other",
str_detect(label, "Two or More Races") ~ "Two or more races",
str_detect(label, "Hispanic") ~ "Hispanic",
str_detect(label, "Total") ~ "Total",
TRUE ~ label,
),
rpt_group = case_when(
name == "P005001" ~ "Total",
between(name, "P005003", "P005010") ~ "Race/ethnicity",
TRUE ~ "Age"
),
rpt_level = case_when(
label %in% c("White", "Black", "Hispanic", "Asian", "Total", "Other") ~ label,
label %in% c("American Indian", "Pacific Islander", "Two or more races") ~ "Other",
label %in% c("Under 5 years", "5 to 9 years", "10 to 14 years") ~ "Under 15 yrs",
between(label, "15 to 17 years", "22 to 24 years") ~ "15 to 24 yrs",
label %in% c("25 to 29 years", "30 to 34 years") ~ "25 to 34 yrs",
label %in% c("35 to 39 years", "40 to 44 years") ~ "35 to 44 yrs",
label %in% c("45 to 49 years", "50 to 54 years") ~ "45 to 54 yrs",
between(label, "55 to 59 years", "62 to 64 years") ~ "55 to 64 yrs",
between(label, "65 and 66 years", "85 years and over") ~ "65+ yrs"
)
) |>
select(variable = name, label, rpt_group, rpt_level)
sf1_2010_vars# A tibble: 55 × 4
variable label rpt_group rpt_level
<chr> <chr> <chr> <chr>
1 P005001 Total Total Total
2 P005003 White Race/ethnicity White
3 P005004 Black Race/ethnicity Black
4 P005005 American Indian Race/ethnicity Other
5 P005006 Asian Race/ethnicity Asian
6 P005007 Pacific Islander Race/ethnicity Other
7 P005008 Other Race/ethnicity Other
8 P005009 Two or more races Race/ethnicity Other
9 P005010 Hispanic Race/ethnicity Hispanic
10 P012003 Under 5 years Age Under 15 yrs
# ℹ 45 more rows
Request the data from the API.
Show the code
downtown_core_tracts_2010 <- c(
"103300", "107101", "107701", "107802", "109301")
downtown_core_blocks_2010 <-
paste0("39035108701", c("3000", "3001", "3002", "3003", "3004"))
if (USE_API) {
subdiv_2010 <-
get_decennial(
geography = "county subdivision",
sumfile = "sf1",
variables = sf1_2010_vars$variable,
state = "OH",
county = "Cuyahoga",
geometry = TRUE,
year = 2010
) |>
inner_join(sf1_2010_vars, by = "variable") |>
summarize(
.by = c(GEOID, NAME, geometry, rpt_group, rpt_level),
value = sum(value)
) |>
mutate(
rpt_level = my_rpt_relevel(rpt_level),
NAME = str_remove_all(NAME, "(, Cuyahoga County, Ohio)|(village)|(city)"),
NAME = str_trim(NAME)
)
tract_2010 <-
get_decennial(
geography = "tract",
sumfile = "sf1",
variables = sf1_2010_vars$variable,
state = "OH",
county = "Cuyahoga",
geometry = TRUE,
year = 2010
) |>
inner_join(sf1_2010_vars, by = "variable") |>
summarize(
.by = c(GEOID, NAME, geometry, rpt_group, rpt_level),
value = sum(value)
) |>
mutate(rpt_level = my_rpt_relevel(rpt_level))
block_2010_0 <-
get_decennial(
geography = "block",
sumfile = "sf1",
variables = sf1_2010_vars$variable,
state = "OH",
county = "Cuyahoga",
geometry = TRUE,
year = 2010
) |>
inner_join(sf1_2010_vars, by = "variable") |>
summarize(
.by = c(GEOID, NAME, geometry, rpt_group, rpt_level),
value = sum(value)
) |>
mutate(rpt_level = my_rpt_relevel(rpt_level))
block_2010 <-
st_join(cleve_neigh, st_centroid(block_2010_0), join = st_contains) |>
mutate(
rpt_level = my_rpt_relevel(rpt_level),
greater_downtown = case_when(
str_sub(GEOID, 6, 11) %in% westside_tracts ~ "Westside",
str_sub(GEOID, 6, 11) %in% downtown_core_tracts_2010 ~ "Downtown Core",
GEOID %in% downtown_core_blocks_2010 ~ "Downtown Core",
TRUE ~ "Other"
),
SPA = factor(str_to_title(SPA)),
SPA = fct_relevel(SPA, "Downtown", after = 0),
greater_downtown = factor(
greater_downtown, levels = c("Downtown Core", "Westside", "Other"))
) |>
select(GEOID, NAME, geometry, rpt_group, rpt_level, value, SPA, greater_downtown)
save(
subdiv_2010, tract_2010, block_2010,
file = "decennial_2010.Rdata"
)
} else {
load("decennial_2010.Rdata")
}The sum of the neighborhoods, 395,601, didn’t quite roll match the city, 396,815. There must be city blocks whose centers are not captured in the neighborhoods shape. I haven’t thought of a good way to ferret them out, so I think I’ll just let this go.
The Downtown population was only 9,464, so it has indeed grown quite a bit from 2010 to 2020.
| 2010 Population Estimates for Cleveland and Vicinity | |
|---|---|
| Population | |
| Cuyahoga County Subdivisions | |
| Cleveland | 396,815 |
| Other | 883,307 |
| Total | 1,280,122 |
| Cleveland Neighborhoods | |
| Downtown | 9,464 |
| Bellaire-Puritas | 13,380 |
| Broadway-Slavic Village | 22,331 |
| Brooklyn Centre | 8,948 |
| Buckeye Shaker | 12,470 |
| Central | 12,306 |
| Clark Fulton | 8,509 |
| Collinwood Nottingham | 11,542 |
| Cudell | 9,295 |
| Cuyahoga Valley | 1,378 |
| Detroit-Shoreway | 11,577 |
| Edgewater | 5,851 |
| Euclid Green | 4,873 |
| Fairfax | 6,239 |
| Glenville | 27,394 |
| Goodrich-Kirtland Park | 4,238 |
| Hopkins | 646 |
| Hough | 11,490 |
| Jefferson | 16,548 |
| Kamms Corners | 24,097 |
| Kinsman | 6,966 |
| Lee-Harvard | 10,326 |
| Lee-Seville | 4,477 |
| Mount Pleasant | 17,320 |
| North Shore Collinwood | 15,768 |
| Ohio City | 8,396 |
| Old Brooklyn | 32,009 |
| Saint Clair-Superior | 6,876 |
| Stockyards | 10,411 |
| Tremont | 7,975 |
| Union-Miles Park | 19,004 |
| University Circle | 7,939 |
| West Boulevard | 18,880 |
| Woodland Hills | 6,678 |
| Total | 395,601 |
| Greater Downtown | |
| Downtown Core | 15,156 |
| Westside | 18,433 |
| Other | 362,012 |
| Total | 395,601 |
2000
2000 is similar to 2010 in that it uses Summary File 1.
sf1_2000_vars <-
tidycensus::load_variables(2000, "sf1") |>
filter(
concept %in% c(
"HISPANIC OR LATINO, AND NOT HISPANIC OR LATINO BY RACE [73]",
"SEX BY AGE [49]"
),
!name %in% c("P004003", "P004004", "P012001", "P012002", "P012026"),
!str_detect(label, "Population of two or more races!!"),
!str_detect(name, "^PCT013")
)Show the code
sf1_2000_vars <-
sf1_2000_vars |>
mutate(
label = str_remove(label, "(Total!!Male!!)|(Total!!Female!!)"),
label = case_when(
str_detect(label, "White") ~ "White",
str_detect(label, "Black") ~ "Black",
str_detect(label, "Asian") ~ "Asian",
str_detect(label, "American Indian") ~ "American Indian",
str_detect(label, "Native Hawaiian") ~ "Pacific Islander",
str_detect(label, "Some Other Race") ~ "Other",
str_detect(label, "Two or More Races") ~ "Two or more races",
str_detect(label, "Hispanic") ~ "Hispanic",
str_detect(label, "Total") ~ "Total",
TRUE ~ label,
),
rpt_group = case_when(
name == "P004001" ~ "Total",
between(name, "P004002", "P004011") ~ "Race/ethnicity",
TRUE ~ "Age"
),
rpt_level = case_when(
label %in% c("White", "Black", "Hispanic", "Asian", "Total", "Other") ~ label,
label %in% c("American Indian", "Pacific Islander", "Two or more races") ~ "Other",
label %in% c("Under 5 years", "5 to 9 years", "10 to 14 years") ~ "Under 15 yrs",
between(label, "15 to 17 years", "22 to 24 years") ~ "15 to 24 yrs",
label %in% c("25 to 29 years", "30 to 34 years") ~ "25 to 34 yrs",
label %in% c("35 to 39 years", "40 to 44 years") ~ "35 to 44 yrs",
label %in% c("45 to 49 years", "50 to 54 years") ~ "45 to 54 yrs",
between(label, "55 to 59 years", "62 to 64 years") ~ "55 to 64 yrs",
between(label, "65 and 66 years", "85 years and over") ~ "65+ yrs"
)
) |>
select(variable = name, label, rpt_group, rpt_level)
sf1_2010_vars# A tibble: 55 × 4
variable label rpt_group rpt_level
<chr> <chr> <chr> <chr>
1 P005001 Total Total Total
2 P005003 White Race/ethnicity White
3 P005004 Black Race/ethnicity Black
4 P005005 American Indian Race/ethnicity Other
5 P005006 Asian Race/ethnicity Asian
6 P005007 Pacific Islander Race/ethnicity Other
7 P005008 Other Race/ethnicity Other
8 P005009 Two or more races Race/ethnicity Other
9 P005010 Hispanic Race/ethnicity Hispanic
10 P012003 Under 5 years Age Under 15 yrs
# ℹ 45 more rows
Request the data from the API.
Show the code
downtown_core_tracts_2000 <- c(
"107100", "107200", "107300", "107400", "107500", "107600", "107700",
"107800", "107900", "109200")
# "103300", "107101", "107701", "107802", "109301")
downtown_core_blocks_2000 <-
paste0("39035108701", c("3000", "3001", "3002", "3003", "3004"))
if (USE_API) {
subdiv_2000_0 <-
get_decennial(
geography = "county subdivision",
sumfile = "sf1",
variables = sf1_2000_vars$variable,
state = "OH",
county = "Cuyahoga",
geometry = FALSE, # no county subdivision geography in 2000
year = 2000
) |>
inner_join(sf1_2000_vars, by = "variable") |>
summarize(
.by = c(GEOID, NAME, rpt_group, rpt_level),
value = sum(value)
) |>
mutate(
rpt_level = my_rpt_relevel(rpt_level),
NAME = str_remove_all(NAME, "(, Cuyahoga County, Ohio)|(village)|(city)"),
NAME = str_trim(NAME)
)
# No geometry for 2000? No problem? I'll use the 2010 geometry and replace the
# values with 2000.
subdiv_2000_1 <-
subdiv_2000_0 |>
as_tibble() |>
select(GEOID, rpt_group, rpt_level, value)
subdiv_2000 <-
subdiv_2010 |>
select(-value) |>
inner_join(subdiv_2000_1, by = c("GEOID", "rpt_group", "rpt_level"))
tract_2000 <-
get_decennial(
geography = "tract",
sumfile = "sf1",
variables = sf1_2000_vars$variable,
state = "OH",
county = "Cuyahoga",
geometry = TRUE,
year = 2000
) |>
inner_join(sf1_2000_vars, by = "variable") |>
summarize(
.by = c(GEOID, NAME, geometry, rpt_group, rpt_level),
value = sum(value)
) |>
mutate(rpt_level = my_rpt_relevel(rpt_level))
block_2000_0 <-
get_decennial(
geography = "block",
sumfile = "sf1",
variables = sf1_2000_vars$variable,
state = "OH",
county = "Cuyahoga",
geometry = TRUE,
year = 2000
) |>
inner_join(sf1_2000_vars, by = "variable") |>
summarize(
.by = c(GEOID, NAME, geometry, rpt_group, rpt_level),
value = sum(value)
) |>
mutate(rpt_level = my_rpt_relevel(rpt_level))
block_2000 <-
st_join(cleve_neigh, st_centroid(block_2000_0), join = st_contains) |>
mutate(
rpt_level = my_rpt_relevel(rpt_level),
greater_downtown = case_when(
str_sub(GEOID, 6, 11) %in% westside_tracts ~ "Westside",
str_sub(GEOID, 6, 11) %in% downtown_core_tracts_2000 ~ "Downtown Core",
GEOID %in% downtown_core_blocks_2000 ~ "Downtown Core",
TRUE ~ "Other"
),
SPA = factor(str_to_title(SPA)),
SPA = fct_relevel(SPA, "Downtown", after = 0),
greater_downtown = factor(
greater_downtown, levels = c("Downtown Core", "Westside", "Other"))
) |>
select(GEOID, NAME, geometry, rpt_group, rpt_level, value, SPA, greater_downtown)
save(
subdiv_2000, tract_2000, block_2000,
file = "decennial_2000.Rdata"
)
} else {
load("decennial_2000.Rdata")
}We have the same problem as 2010 - the sum of the neighborhoods, 477,107, didn’t quite roll match the city, 478,403.
Wow, Cleveland’s population was 478,403 in 2000 - that’s a 100K more than today! It sure has dropped a lot over the last two decades. On the other hand, only 6,310 people lived downtown. The resurgence of Downtown does not seem to be a recent phenomena.
| 2000 Population Estimates for Cleveland and Vicinity | |
|---|---|
| Population | |
| Cuyahoga County Subdivisions | |
| Cleveland | 478,403 |
| Other | 915,575 |
| Total | 1,393,978 |
| Cleveland Neighborhoods | |
| Downtown | 6,310 |
| Bellaire-Puritas | 14,520 |
| Broadway-Slavic Village | 30,652 |
| Brooklyn Centre | 10,155 |
| Buckeye Shaker | 16,063 |
| Central | 11,568 |
| Clark Fulton | 10,672 |
| Collinwood Nottingham | 15,874 |
| Cudell | 10,630 |
| Cuyahoga Valley | 1,307 |
| Detroit-Shoreway | 13,917 |
| Edgewater | 6,360 |
| Euclid Green | 6,169 |
| Fairfax | 8,447 |
| Glenville | 39,941 |
| Goodrich-Kirtland Park | 4,580 |
| Hopkins | 338 |
| Hough | 14,734 |
| Jefferson | 18,266 |
| Kamms Corners | 25,256 |
| Kinsman | 10,256 |
| Lee-Harvard | 11,665 |
| Lee-Seville | 5,595 |
| Mount Pleasant | 24,013 |
| North Shore Collinwood | 18,346 |
| Ohio City | 8,726 |
| Old Brooklyn | 34,169 |
| Saint Clair-Superior | 11,534 |
| Stockyards | 12,076 |
| Tremont | 9,317 |
| Union-Miles Park | 26,539 |
| University Circle | 9,386 |
| West Boulevard | 20,492 |
| Woodland Hills | 9,234 |
| Total | 477,107 |
| Greater Downtown | |
| Downtown Core | 8,412 |
| Westside | 15,154 |
| Other | 453,541 |
| Total | 477,107 |
2023 (ACS)
The 2023 American Community Survey publishes a 1-year and 5-year average. We’ll grab the 1-year to get the latest population figures.
acs1_2023_vars <-
tidycensus::load_variables(2023, "acs1") |>
filter(
concept %in% c("Sex by Age", "Hispanic or Latino Origin by Race"),
# between(name, "B01001_001E_001N", "P2_011N"),
!name %in% c("B01001_002", "B01001_026", "B03002_001", "B03002_002",
"B03002_010", "B03002_011"),
name <= "B03002_012"
)Show the code
acs1_2023_vars <-
acs1_2023_vars |>
mutate(
label = str_remove_all(label, "(Estimate!!Total:!!)|(Male:!!)|(Female:!!)"),
label = case_when(
str_detect(label, "White") ~ "White",
str_detect(label, "Black") ~ "Black",
str_detect(label, "Asian") ~ "Asian",
str_detect(label, "American Indian") ~ "American Indian",
str_detect(label, "Native Hawaiian") ~ "Pacific Islander",
str_detect(label, "Some other race") ~ "Other",
str_detect(label, "Two or more races") ~ "Two or more races",
str_detect(label, "Hispanic") ~ "Hispanic",
str_detect(label, "Total") ~ "Total",
TRUE ~ label,
),
rpt_group = case_when(
name == "B01001_001" ~ "Total",
between(name, "B03002_003", "B03002_012") ~ "Race/ethnicity",
TRUE ~ "Age"
),
rpt_level = case_when(
label %in% c("White", "Black", "Hispanic", "Asian", "Total", "Other") ~ label,
label %in% c("American Indian", "Pacific Islander", "Two or more races") ~ "Other",
label %in% c("Under 5 years", "5 to 9 years", "10 to 14 years") ~ "Under 15 yrs",
between(label, "15 to 17 years", "22 to 24 years") ~ "15 to 24 yrs",
label %in% c("25 to 29 years", "30 to 34 years") ~ "25 to 34 yrs",
label %in% c("35 to 39 years", "40 to 44 years") ~ "35 to 44 yrs",
label %in% c("45 to 49 years", "50 to 54 years") ~ "45 to 54 yrs",
between(label, "55 to 59 years", "62 to 64 years") ~ "55 to 64 yrs",
between(label, "65 and 66 years", "85 years and over") ~ "65+ yrs"
)
) |>
select(variable = name, label, rpt_group, rpt_level)
acs1_2023_vars# A tibble: 55 × 4
variable label rpt_group rpt_level
<chr> <chr> <chr> <chr>
1 B01001_001 Total Total Total
2 B01001_003 Under 5 years Age Under 15 yrs
3 B01001_004 5 to 9 years Age Under 15 yrs
4 B01001_005 10 to 14 years Age Under 15 yrs
5 B01001_006 15 to 17 years Age 15 to 24 yrs
6 B01001_007 18 and 19 years Age 15 to 24 yrs
7 B01001_008 20 years Age 15 to 24 yrs
8 B01001_009 21 years Age 15 to 24 yrs
9 B01001_010 22 to 24 years Age 15 to 24 yrs
10 B01001_011 25 to 29 years Age 25 to 34 yrs
# ℹ 45 more rows
Request the data from the API.
Show the code
if (USE_API) {
subdiv_2023 <-
get_acs(
geography = "county subdivision",
sumfile = "acs1",
variables = acs1_2023_vars$variable,
state = "OH",
county = "Cuyahoga",
geometry = FALSE, # no geo file for ACS-1yr
year = 2023
) |>
inner_join(acs1_2023_vars, by = "variable") |>
summarize(
.by = c(GEOID, NAME, rpt_group, rpt_level),
value = sum(estimate)
) |>
mutate(
rpt_level = my_rpt_relevel(rpt_level),
NAME = str_remove_all(NAME, "(, Cuyahoga County, Ohio)|(village)|(city)"),
NAME = str_trim(NAME)
)
tract_2023 <-
get_acs(
geography = "tract",
sumfile = "acs1",
variables = acs1_2023_vars$variable,
state = "OH",
county = "Cuyahoga",
geometry = FALSE,
year = 2023
) |>
inner_join(acs1_2023_vars, by = "variable") |>
summarize(
.by = c(GEOID, NAME, rpt_group, rpt_level),
value = sum(estimate)
) |>
mutate(rpt_level = my_rpt_relevel(rpt_level))
save(
subdiv_2023, tract_2023,
file = "acs1yr_2023.Rdata"
)
} else {
load("acs1yr_2023.Rdata")
}Cleveland’s population has continued to decline, down from 372,624 in 2020 to 367,523. The ACS does not have block-level data, so I can’t do the neighborhood breakdown here.
But look at Downtown - it’s continued to increase.
| 2023 Population Estimates for Cleveland and Vicinity | |
|---|---|
| Population | |
| Cleveland | 367,523 |
| Other | 881,895 |
| Total | 1,249,418 |
Show the code
# 34 features (neighborhoods).
hood_shp <-
st_read("Cleveland_Neighborhoods/Cleveland_Neighborhoods.shp") |>
st_make_valid() |>
st_transform(st_crs(tract_2000))
hood_2023 <-
tract_2023 |>
inner_join(hood_2020 |> select(GEOID, SPANM) |> unique(), by = "GEOID")
hood_shp <-
st_read("Cleveland_Neighborhoods/Cleveland_Neighborhoods.shp") |>
st_make_valid() |>
st_transform(st_crs(tract_2000))
hood_2000 <- st_join(hood_shp, st_centroid(tract_2000), join = st_contains)Population Trends
Downtown Cleveland Inc. defined “Greater Downtown Cleveland” in their report as the “Downtown Core” on the east side of the Cuyahoga and “Westside” to west. Their Downtown Core is bounded by about E. 30th St. and Woodland Ave to the South.9. The Westside is bounded mostly by W. 65th St and Clark Avenue to the south. I’m not sure how they came up with this definition. Maybe it was with census blocks. Their Greater Downtown includes 37,115 people with 18,708 in the Downtown Core. I’ll stick with the neighborhoods definition.
Let’s start with a neighborhood table showing the population changes since 2000. The Downtown population was only 8,227 in 2000 - 2% of Cleveland’s 478,403 population. Cleveland’s population fell 17% over the next decade. Hit hardest the east side neighborhoods such as Buckeye-Woodhill, Glenville, Kinsman, Lee-Seville, and St.Clair-Superior, all of which lost over 30% of their population. However, Downtown experienced a 15% population increase over this period.
| Changing Total Population in Cleveland, 2000-2023 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Decennial and ACS censuses | ||||||||||
| 2000 | 2010 | Δ | % | 2020 | Δ | % | 2023 | Δ | % | |
| Bellaire-Puritas | 14,520 | 13,380 | −1,140 | −8% | 13,823 | 443 | 3% | NA | NA | NA |
| Broadway-Slavic Village | 30,652 | 22,331 | −8,321 | −27% | 19,022 | −3,309 | −15% | NA | NA | NA |
| Brooklyn Centre | 10,155 | 8,948 | −1,207 | −12% | 8,315 | −633 | −7% | NA | NA | NA |
| Buckeye Shaker | 16,063 | 12,470 | −3,593 | −22% | 11,419 | −1,051 | −8% | NA | NA | NA |
| Central | 11,568 | 12,306 | 738 | 6% | 11,955 | −351 | −3% | NA | NA | NA |
| Clark Fulton | 10,672 | 8,509 | −2,163 | −20% | 7,625 | −884 | −10% | NA | NA | NA |
| Collinwood Nottingham | 15,874 | 11,542 | −4,332 | −27% | 9,616 | −1,926 | −17% | NA | NA | NA |
| Cudell | 10,630 | 9,295 | −1,335 | −13% | 9,115 | −180 | −2% | NA | NA | NA |
| Cuyahoga Valley | 1,307 | 1,378 | 71 | 5% | 1,293 | −85 | −6% | NA | NA | NA |
| Detroit-Shoreway | 13,917 | 11,577 | −2,340 | −17% | 11,326 | −251 | −2% | NA | NA | NA |
| Downtown | 6,310 | 9,464 | 3,154 | 50% | 13,302 | 3,838 | 41% | NA | NA | NA |
| Edgewater | 6,360 | 5,851 | −509 | −8% | 6,000 | 149 | 3% | NA | NA | NA |
| Euclid Green | 6,169 | 4,873 | −1,296 | −21% | 5,051 | 178 | 4% | NA | NA | NA |
| Fairfax | 8,447 | 6,239 | −2,208 | −26% | 5,167 | −1,072 | −17% | NA | NA | NA |
| Glenville | 39,941 | 27,394 | −12,547 | −31% | 21,137 | −6,257 | −23% | NA | NA | NA |
| Goodrich-Kirtland Park | 4,580 | 4,238 | −342 | −7% | 3,955 | −283 | −7% | NA | NA | NA |
| Hopkins | 338 | 646 | 308 | 91% | 534 | −112 | −17% | NA | NA | NA |
| Hough | 14,734 | 11,490 | −3,244 | −22% | 9,702 | −1,788 | −16% | NA | NA | NA |
| Jefferson | 18,266 | 16,548 | −1,718 | −9% | 17,351 | 803 | 5% | NA | NA | NA |
| Kamms Corners | 25,256 | 24,097 | −1,159 | −5% | 24,312 | 215 | 1% | NA | NA | NA |
| Kinsman | 10,256 | 6,966 | −3,290 | −32% | 5,876 | −1,090 | −16% | NA | NA | NA |
| Lee-Harvard | 11,665 | 10,326 | −1,339 | −11% | 9,770 | −556 | −5% | NA | NA | NA |
| Lee-Seville | 5,595 | 4,477 | −1,118 | −20% | 4,171 | −306 | −7% | NA | NA | NA |
| Mount Pleasant | 24,013 | 17,320 | −6,693 | −28% | 14,015 | −3,305 | −19% | NA | NA | NA |
| North Shore Collinwood | 18,346 | 15,768 | −2,578 | −14% | 14,928 | −840 | −5% | NA | NA | NA |
| Ohio City | 8,726 | 8,396 | −330 | −4% | 9,219 | 823 | 10% | NA | NA | NA |
| Old Brooklyn | 34,169 | 32,009 | −2,160 | −6% | 32,315 | 306 | 1% | NA | NA | NA |
| Saint Clair-Superior | 11,534 | 6,876 | −4,658 | −40% | 5,139 | −1,737 | −25% | NA | NA | NA |
| Stockyards | 12,076 | 10,411 | −1,665 | −14% | 9,522 | −889 | −9% | NA | NA | NA |
| Tremont | 9,317 | 7,975 | −1,342 | −14% | 7,798 | −177 | −2% | NA | NA | NA |
| Union-Miles Park | 26,539 | 19,004 | −7,535 | −28% | 15,625 | −3,379 | −18% | NA | NA | NA |
| University Circle | 9,386 | 7,939 | −1,447 | −15% | 9,620 | 1,681 | 21% | NA | NA | NA |
| West Boulevard | 20,492 | 18,880 | −1,612 | −8% | 18,981 | 101 | 1% | NA | NA | NA |
| Woodland Hills | 9,234 | 6,678 | −2,556 | −28% | 5,625 | −1,053 | −16% | NA | NA | NA |
| Total | 478,403 | 396,815 | −81,588 | −17% | 372,624 | −24,191 | −6% | 367,523 | −5,101 | −1% |
Race/ethnicity
Show the code
neigh_gt("Race/ethnicity", "Black")| Changing Black Population in Cleveland, 2000-2023 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Decennial and ACS censuses | ||||||||||
| 2000 | 2010 | Δ | % | 2020 | Δ | % | 2023 | Δ | % | |
| Bellaire-Puritas | 3,092 | 3,356 | 264 | 9% | 3,215 | −141 | −4% | NA | NA | NA |
| Broadway-Slavic Village | 7,910 | 11,576 | 3,666 | 46% | 10,225 | −1,351 | −12% | NA | NA | NA |
| Brooklyn Centre | 1,102 | 1,751 | 649 | 59% | 1,724 | −27 | −2% | NA | NA | NA |
| Buckeye Shaker | 12,783 | 10,064 | −2,719 | −21% | 8,583 | −1,481 | −15% | NA | NA | NA |
| Central | 10,926 | 11,505 | 579 | 5% | 9,997 | −1,508 | −13% | NA | NA | NA |
| Clark Fulton | 1,000 | 1,441 | 441 | 44% | 1,378 | −63 | −4% | NA | NA | NA |
| Collinwood Nottingham | 12,261 | 10,021 | −2,240 | −18% | 8,329 | −1,692 | −17% | NA | NA | NA |
| Cudell | 1,724 | 2,976 | 1,252 | 73% | 2,879 | −97 | −3% | NA | NA | NA |
| Cuyahoga Valley | 609 | 566 | −43 | −7% | 260 | −306 | −54% | NA | NA | NA |
| Detroit-Shoreway | 2,487 | 2,867 | 380 | 15% | 2,309 | −558 | −19% | NA | NA | NA |
| Downtown | 3,448 | 4,140 | 692 | 20% | 3,430 | −710 | −17% | NA | NA | NA |
| Edgewater | 742 | 1,194 | 452 | 61% | 867 | −327 | −27% | NA | NA | NA |
| Euclid Green | 5,607 | 4,524 | −1,083 | −19% | 4,472 | −52 | −1% | NA | NA | NA |
| Fairfax | 8,002 | 5,932 | −2,070 | −26% | 4,637 | −1,295 | −22% | NA | NA | NA |
| Glenville | 38,918 | 26,516 | −12,402 | −32% | 19,524 | −6,992 | −26% | NA | NA | NA |
| Goodrich-Kirtland Park | 849 | 985 | 136 | 16% | 908 | −77 | −8% | NA | NA | NA |
| Hopkins | 9 | 131 | 122 | 1,356% | 148 | 17 | 13% | NA | NA | NA |
| Hough | 14,131 | 10,896 | −3,235 | −23% | 8,453 | −2,443 | −22% | NA | NA | NA |
| Jefferson | 1,663 | 2,604 | 941 | 57% | 3,106 | 502 | 19% | NA | NA | NA |
| Kamms Corners | 1,702 | 2,503 | 801 | 47% | 2,229 | −274 | −11% | NA | NA | NA |
| Kinsman | 9,903 | 6,696 | −3,207 | −32% | 5,480 | −1,216 | −18% | NA | NA | NA |
| Lee-Harvard | 11,380 | 10,012 | −1,368 | −12% | 9,263 | −749 | −7% | NA | NA | NA |
| Lee-Seville | 5,367 | 4,317 | −1,050 | −20% | 3,914 | −403 | −9% | NA | NA | NA |
| Mount Pleasant | 23,394 | 16,817 | −6,577 | −28% | 13,175 | −3,642 | −22% | NA | NA | NA |
| North Shore Collinwood | 9,065 | 10,359 | 1,294 | 14% | 10,310 | −49 | −0% | NA | NA | NA |
| Ohio City | 2,159 | 2,718 | 559 | 26% | 2,082 | −636 | −23% | NA | NA | NA |
| Old Brooklyn | 836 | 2,337 | 1,501 | 180% | 3,657 | 1,320 | 56% | NA | NA | NA |
| Saint Clair-Superior | 8,628 | 5,347 | −3,281 | −38% | 3,743 | −1,604 | −30% | NA | NA | NA |
| Stockyards | 1,043 | 1,729 | 686 | 66% | 1,605 | −124 | −7% | NA | NA | NA |
| Tremont | 1,669 | 1,721 | 52 | 3% | 1,166 | −555 | −32% | NA | NA | NA |
| Union-Miles Park | 25,523 | 18,339 | −7,184 | −28% | 14,566 | −3,773 | −21% | NA | NA | NA |
| University Circle | 2,767 | 1,849 | −918 | −33% | 1,696 | −153 | −8% | NA | NA | NA |
| West Boulevard | 1,964 | 3,589 | 1,625 | 83% | 4,234 | 645 | 18% | NA | NA | NA |
| Woodland Hills | 8,839 | 6,409 | −2,430 | −27% | 5,249 | −1,160 | −18% | NA | NA | NA |
| Total | 241,512 | 208,208 | −33,304 | −14% | 176,813 | −31,395 | −15% | 169,138 | −7,675 | −4% |
Show the code
neigh_gt("Race/ethnicity", "White")| Changing White Population in Cleveland, 2000-2023 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Decennial and ACS censuses | ||||||||||
| 2000 | 2010 | Δ | % | 2020 | Δ | % | 2023 | Δ | % | |
| Bellaire-Puritas | 9,761 | 7,479 | −2,282 | −23% | 6,050 | −1,429 | −19% | NA | NA | NA |
| Broadway-Slavic Village | 20,498 | 8,822 | −11,676 | −57% | 5,988 | −2,834 | −32% | NA | NA | NA |
| Brooklyn Centre | 5,937 | 3,962 | −1,975 | −33% | 3,033 | −929 | −23% | NA | NA | NA |
| Buckeye Shaker | 2,420 | 1,602 | −818 | −34% | 1,707 | 105 | 7% | NA | NA | NA |
| Central | 320 | 418 | 98 | 31% | 522 | 104 | 25% | NA | NA | NA |
| Clark Fulton | 4,449 | 2,789 | −1,660 | −37% | 1,942 | −847 | −30% | NA | NA | NA |
| Collinwood Nottingham | 3,099 | 1,145 | −1,954 | −63% | 736 | −409 | −36% | NA | NA | NA |
| Cudell | 6,220 | 3,813 | −2,407 | −39% | 3,279 | −534 | −14% | NA | NA | NA |
| Cuyahoga Valley | 643 | 714 | 71 | 11% | 893 | 179 | 25% | NA | NA | NA |
| Detroit-Shoreway | 7,516 | 5,257 | −2,259 | −30% | 5,591 | 334 | 6% | NA | NA | NA |
| Downtown | 2,380 | 4,061 | 1,681 | 71% | 7,550 | 3,489 | 86% | NA | NA | NA |
| Edgewater | 4,926 | 3,865 | −1,061 | −22% | 4,089 | 224 | 6% | NA | NA | NA |
| Euclid Green | 390 | 223 | −167 | −43% | 186 | −37 | −17% | NA | NA | NA |
| Fairfax | 221 | 130 | −91 | −41% | 195 | 65 | 50% | NA | NA | NA |
| Glenville | 328 | 238 | −90 | −27% | 473 | 235 | 99% | NA | NA | NA |
| Goodrich-Kirtland Park | 1,825 | 1,479 | −346 | −19% | 1,077 | −402 | −27% | NA | NA | NA |
| Hopkins | 299 | 419 | 120 | 40% | 229 | −190 | −45% | NA | NA | NA |
| Hough | 272 | 245 | −27 | −10% | 417 | 172 | 70% | NA | NA | NA |
| Jefferson | 14,155 | 10,246 | −3,909 | −28% | 8,676 | −1,570 | −15% | NA | NA | NA |
| Kamms Corners | 21,777 | 18,685 | −3,092 | −14% | 17,643 | −1,042 | −6% | NA | NA | NA |
| Kinsman | 168 | 101 | −67 | −40% | 118 | 17 | 17% | NA | NA | NA |
| Lee-Harvard | 99 | 63 | −36 | −36% | 90 | 27 | 43% | NA | NA | NA |
| Lee-Seville | 102 | 32 | −70 | −69% | 48 | 16 | 50% | NA | NA | NA |
| Mount Pleasant | 146 | 112 | −34 | −23% | 166 | 54 | 48% | NA | NA | NA |
| North Shore Collinwood | 8,650 | 4,853 | −3,797 | −44% | 3,659 | −1,194 | −25% | NA | NA | NA |
| Ohio City | 4,327 | 3,657 | −670 | −15% | 5,087 | 1,430 | 39% | NA | NA | NA |
| Old Brooklyn | 30,167 | 24,066 | −6,101 | −20% | 19,307 | −4,759 | −20% | NA | NA | NA |
| Saint Clair-Superior | 1,904 | 1,028 | −876 | −46% | 782 | −246 | −24% | NA | NA | NA |
| Stockyards | 7,203 | 4,614 | −2,589 | −36% | 3,418 | −1,196 | −26% | NA | NA | NA |
| Tremont | 4,899 | 4,094 | −805 | −16% | 4,583 | 489 | 12% | NA | NA | NA |
| Union-Miles Park | 502 | 263 | −239 | −48% | 299 | 36 | 14% | NA | NA | NA |
| University Circle | 5,135 | 4,279 | −856 | −17% | 4,722 | 443 | 10% | NA | NA | NA |
| West Boulevard | 13,550 | 9,098 | −4,452 | −33% | 6,882 | −2,216 | −24% | NA | NA | NA |
| Woodland Hills | 201 | 139 | −62 | −31% | 110 | −29 | −21% | NA | NA | NA |
| Total | 185,641 | 132,710 | −52,931 | −29% | 119,547 | −13,163 | −10% | 124,183 | 4,636 | 4% |
Show the code
neigh_gt("Race/ethnicity", "Hispanic")| Changing Hispanic Population in Cleveland, 2000-2023 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Decennial and ACS censuses | ||||||||||
| 2000 | 2010 | Δ | % | 2020 | Δ | % | 2023 | Δ | % | |
| Bellaire-Puritas | 1,263 | 1,749 | 486 | 38% | 2,967 | 1,218 | 70% | NA | NA | NA |
| Broadway-Slavic Village | 2,077 | 1,206 | −871 | −42% | 1,664 | 458 | 38% | NA | NA | NA |
| Brooklyn Centre | 3,003 | 2,869 | −134 | −4% | 2,957 | 88 | 3% | NA | NA | NA |
| Buckeye Shaker | 501 | 178 | −323 | −64% | 281 | 103 | 58% | NA | NA | NA |
| Central | 291 | 205 | −86 | −30% | 962 | 757 | 369% | NA | NA | NA |
| Clark Fulton | 5,095 | 4,013 | −1,082 | −21% | 3,804 | −209 | −5% | NA | NA | NA |
| Collinwood Nottingham | 455 | 177 | −278 | −61% | 216 | 39 | 22% | NA | NA | NA |
| Cudell | 2,120 | 1,811 | −309 | −15% | 2,031 | 220 | 12% | NA | NA | NA |
| Cuyahoga Valley | 51 | 49 | −2 | −4% | 73 | 24 | 49% | NA | NA | NA |
| Detroit-Shoreway | 3,657 | 2,886 | −771 | −21% | 2,548 | −338 | −12% | NA | NA | NA |
| Downtown | 325 | 313 | −12 | −4% | 707 | 394 | 126% | NA | NA | NA |
| Edgewater | 552 | 507 | −45 | −8% | 510 | 3 | 1% | NA | NA | NA |
| Euclid Green | 141 | 40 | −101 | −72% | 193 | 153 | 382% | NA | NA | NA |
| Fairfax | 194 | 37 | −157 | −81% | 95 | 58 | 157% | NA | NA | NA |
| Glenville | 595 | 202 | −393 | −66% | 356 | 154 | 76% | NA | NA | NA |
| Goodrich-Kirtland Park | 656 | 439 | −217 | −33% | 550 | 111 | 25% | NA | NA | NA |
| Hopkins | 17 | 56 | 39 | 229% | 105 | 49 | 88% | NA | NA | NA |
| Hough | 290 | 152 | −138 | −48% | 297 | 145 | 95% | NA | NA | NA |
| Jefferson | 2,091 | 2,944 | 853 | 41% | 3,828 | 884 | 30% | NA | NA | NA |
| Kamms Corners | 1,368 | 1,762 | 394 | 29% | 2,244 | 482 | 27% | NA | NA | NA |
| Kinsman | 161 | 58 | −103 | −64% | 94 | 36 | 62% | NA | NA | NA |
| Lee-Harvard | 160 | 83 | −77 | −48% | 113 | 30 | 36% | NA | NA | NA |
| Lee-Seville | 117 | 34 | −83 | −71% | 69 | 35 | 103% | NA | NA | NA |
| Mount Pleasant | 440 | 145 | −295 | −67% | 194 | 49 | 34% | NA | NA | NA |
| North Shore Collinwood | 517 | 197 | −320 | −62% | 305 | 108 | 55% | NA | NA | NA |
| Ohio City | 2,135 | 1,720 | −415 | −19% | 1,427 | −293 | −17% | NA | NA | NA |
| Old Brooklyn | 2,691 | 4,414 | 1,723 | 64% | 7,180 | 2,766 | 63% | NA | NA | NA |
| Saint Clair-Superior | 943 | 340 | −603 | −64% | 394 | 54 | 16% | NA | NA | NA |
| Stockyards | 3,630 | 3,645 | 15 | 0% | 3,888 | 243 | 7% | NA | NA | NA |
| Tremont | 2,611 | 1,873 | −738 | −28% | 1,518 | −355 | −19% | NA | NA | NA |
| Union-Miles Park | 468 | 117 | −351 | −75% | 277 | 160 | 137% | NA | NA | NA |
| University Circle | 364 | 179 | −185 | −51% | 554 | 375 | 209% | NA | NA | NA |
| West Boulevard | 4,404 | 5,027 | 623 | 14% | 6,185 | 1,158 | 23% | NA | NA | NA |
| Woodland Hills | 176 | 54 | −122 | −69% | 113 | 59 | 109% | NA | NA | NA |
| Total | 43,648 | 39,534 | −4,114 | −9% | 48,699 | 9,165 | 23% | 47,132 | −1,567 | −3% |
Show the code
neigh_gt("Race/ethnicity", "Asian")| Changing Asian Population in Cleveland, 2000-2023 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Decennial and ACS censuses | ||||||||||
| 2000 | 2010 | Δ | % | 2020 | Δ | % | 2023 | Δ | % | |
| Bellaire-Puritas | 344 | 335 | −9 | −3% | 645 | 310 | 93% | NA | NA | NA |
| Broadway-Slavic Village | 83 | 52 | −31 | −37% | 33 | −19 | −37% | NA | NA | NA |
| Brooklyn Centre | 56 | 53 | −3 | −5% | 83 | 30 | 57% | NA | NA | NA |
| Buckeye Shaker | 332 | 419 | 87 | 26% | 404 | −15 | −4% | NA | NA | NA |
| Central | 9 | 20 | 11 | 122% | 78 | 58 | 290% | NA | NA | NA |
| Clark Fulton | 86 | 45 | −41 | −48% | 100 | 55 | 122% | NA | NA | NA |
| Collinwood Nottingham | 15 | 9 | −6 | −40% | 15 | 6 | 67% | NA | NA | NA |
| Cudell | 523 | 310 | −213 | −41% | 332 | 22 | 7% | NA | NA | NA |
| Cuyahoga Valley | 1 | 34 | 33 | 3,300% | 11 | −23 | −68% | NA | NA | NA |
| Detroit-Shoreway | 177 | 149 | −28 | −16% | 264 | 115 | 77% | NA | NA | NA |
| Downtown | 145 | 731 | 586 | 404% | 1,118 | 387 | 53% | NA | NA | NA |
| Edgewater | 104 | 109 | 5 | 5% | 186 | 77 | 71% | NA | NA | NA |
| Euclid Green | 8 | 6 | −2 | −25% | 6 | 0 | 0% | NA | NA | NA |
| Fairfax | 10 | 50 | 40 | 400% | 90 | 40 | 80% | NA | NA | NA |
| Glenville | 31 | 34 | 3 | 10% | 125 | 91 | 268% | NA | NA | NA |
| Goodrich-Kirtland Park | 1,243 | 1,263 | 20 | 2% | 1,234 | −29 | −2% | NA | NA | NA |
| Hopkins | 13 | 8 | −5 | −38% | 28 | 20 | 250% | NA | NA | NA |
| Hough | 22 | 29 | 7 | 32% | 157 | 128 | 441% | NA | NA | NA |
| Jefferson | 300 | 305 | 5 | 2% | 728 | 423 | 139% | NA | NA | NA |
| Kamms Corners | 358 | 642 | 284 | 79% | 1,044 | 402 | 63% | NA | NA | NA |
| Kinsman | 9 | 9 | 0 | 0% | 10 | 1 | 11% | NA | NA | NA |
| Lee-Harvard | 11 | 12 | 1 | 9% | 14 | 2 | 17% | NA | NA | NA |
| Lee-Seville | 1 | 2 | 1 | 100% | 3 | 1 | 50% | NA | NA | NA |
| Mount Pleasant | 9 | 6 | −3 | −33% | 20 | 14 | 233% | NA | NA | NA |
| North Shore Collinwood | 71 | 34 | −37 | −52% | 48 | 14 | 41% | NA | NA | NA |
| Ohio City | 59 | 82 | 23 | 39% | 218 | 136 | 166% | NA | NA | NA |
| Old Brooklyn | 402 | 414 | 12 | 3% | 392 | −22 | −5% | NA | NA | NA |
| Saint Clair-Superior | 30 | 16 | −14 | −47% | 21 | 5 | 31% | NA | NA | NA |
| Stockyards | 114 | 81 | −33 | −29% | 78 | −3 | −4% | NA | NA | NA |
| Tremont | 70 | 75 | 5 | 7% | 190 | 115 | 153% | NA | NA | NA |
| Union-Miles Park | 14 | 15 | 1 | 7% | 14 | −1 | −7% | NA | NA | NA |
| University Circle | 1,100 | 1,418 | 318 | 29% | 2,200 | 782 | 55% | NA | NA | NA |
| West Boulevard | 483 | 440 | −43 | −9% | 491 | 51 | 12% | NA | NA | NA |
| Woodland Hills | 7 | 2 | −5 | −71% | 10 | 8 | 400% | NA | NA | NA |
| Total | 6,284 | 7,213 | 929 | 15% | 10,390 | 3,177 | 44% | 8,356 | −2,034 | −20% |
Age
| Changing Under 15 yrs Population in Cleveland, 2000-2023 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Decennial and ACS censuses | ||||||||||
| 2000 | 2010 | Δ | % | 2020 | Δ | % | 2023 | Δ | % | |
| Bellaire-Puritas | 3,133 | 2,754 | −379 | −12% | NA | NA | NA | NA | NA | NA |
| Broadway-Slavic Village | 8,256 | 5,373 | −2,883 | −35% | NA | NA | NA | NA | NA | NA |
| Brooklyn Centre | 2,735 | 2,106 | −629 | −23% | NA | NA | NA | NA | NA | NA |
| Buckeye Shaker | 3,471 | 2,048 | −1,423 | −41% | NA | NA | NA | NA | NA | NA |
| Central | 4,372 | 4,717 | 345 | 8% | NA | NA | NA | NA | NA | NA |
| Clark Fulton | 3,204 | 2,102 | −1,102 | −34% | NA | NA | NA | NA | NA | NA |
| Collinwood Nottingham | 4,556 | 2,518 | −2,038 | −45% | NA | NA | NA | NA | NA | NA |
| Cudell | 2,747 | 2,199 | −548 | −20% | NA | NA | NA | NA | NA | NA |
| Cuyahoga Valley | 176 | 129 | −47 | −27% | NA | NA | NA | NA | NA | NA |
| Detroit-Shoreway | 3,650 | 2,472 | −1,178 | −32% | NA | NA | NA | NA | NA | NA |
| Downtown | 267 | 295 | 28 | 10% | NA | NA | NA | NA | NA | NA |
| Edgewater | 800 | 685 | −115 | −14% | NA | NA | NA | NA | NA | NA |
| Euclid Green | 1,552 | 924 | −628 | −40% | NA | NA | NA | NA | NA | NA |
| Fairfax | 2,079 | 1,222 | −857 | −41% | NA | NA | NA | NA | NA | NA |
| Glenville | 10,878 | 5,908 | −4,970 | −46% | NA | NA | NA | NA | NA | NA |
| Goodrich-Kirtland Park | 794 | 569 | −225 | −28% | NA | NA | NA | NA | NA | NA |
| Hopkins | 67 | 128 | 61 | 91% | NA | NA | NA | NA | NA | NA |
| Hough | 4,032 | 2,397 | −1,635 | −41% | NA | NA | NA | NA | NA | NA |
| Jefferson | 4,054 | 3,382 | −672 | −17% | NA | NA | NA | NA | NA | NA |
| Kamms Corners | 5,133 | 4,587 | −546 | −11% | NA | NA | NA | NA | NA | NA |
| Kinsman | 3,408 | 1,812 | −1,596 | −47% | NA | NA | NA | NA | NA | NA |
| Lee-Harvard | 2,051 | 1,636 | −415 | −20% | NA | NA | NA | NA | NA | NA |
| Lee-Seville | 1,274 | 795 | −479 | −38% | NA | NA | NA | NA | NA | NA |
| Mount Pleasant | 6,306 | 3,606 | −2,700 | −43% | NA | NA | NA | NA | NA | NA |
| North Shore Collinwood | 3,867 | 2,793 | −1,074 | −28% | NA | NA | NA | NA | NA | NA |
| Ohio City | 1,854 | 1,440 | −414 | −22% | NA | NA | NA | NA | NA | NA |
| Old Brooklyn | 6,725 | 5,822 | −903 | −13% | NA | NA | NA | NA | NA | NA |
| Saint Clair-Superior | 3,754 | 1,479 | −2,275 | −61% | NA | NA | NA | NA | NA | NA |
| Stockyards | 3,456 | 2,732 | −724 | −21% | NA | NA | NA | NA | NA | NA |
| Tremont | 2,356 | 1,410 | −946 | −40% | NA | NA | NA | NA | NA | NA |
| Union-Miles Park | 7,154 | 3,680 | −3,474 | −49% | NA | NA | NA | NA | NA | NA |
| University Circle | 529 | 247 | −282 | −53% | NA | NA | NA | NA | NA | NA |
| West Boulevard | 5,259 | 4,531 | −728 | −14% | NA | NA | NA | NA | NA | NA |
| Woodland Hills | 3,018 | 1,697 | −1,321 | −44% | NA | NA | NA | NA | NA | NA |
| Total | 117,101 | 80,298 | −36,803 | −31% | 67,636 | −12,662 | −16% | 64,554 | −3,082 | −5% |
| Changing 15 to 24 yrs Population in Cleveland, 2000-2023 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Decennial and ACS censuses | ||||||||||
| 2000 | 2010 | Δ | % | 2020 | Δ | % | 2023 | Δ | % | |
| Bellaire-Puritas | 1,589 | 1,629 | 40 | 3% | NA | NA | NA | NA | NA | NA |
| Broadway-Slavic Village | 4,033 | 3,419 | −614 | −15% | NA | NA | NA | NA | NA | NA |
| Brooklyn Centre | 1,471 | 1,406 | −65 | −4% | NA | NA | NA | NA | NA | NA |
| Buckeye Shaker | 1,929 | 1,678 | −251 | −13% | NA | NA | NA | NA | NA | NA |
| Central | 2,012 | 2,133 | 121 | 6% | NA | NA | NA | NA | NA | NA |
| Clark Fulton | 1,671 | 1,508 | −163 | −10% | NA | NA | NA | NA | NA | NA |
| Collinwood Nottingham | 2,104 | 1,986 | −118 | −6% | NA | NA | NA | NA | NA | NA |
| Cudell | 1,508 | 1,503 | −5 | −0% | NA | NA | NA | NA | NA | NA |
| Cuyahoga Valley | 162 | 412 | 250 | 154% | NA | NA | NA | NA | NA | NA |
| Detroit-Shoreway | 1,932 | 1,664 | −268 | −14% | NA | NA | NA | NA | NA | NA |
| Downtown | 1,576 | 2,445 | 869 | 55% | NA | NA | NA | NA | NA | NA |
| Edgewater | 713 | 690 | −23 | −3% | NA | NA | NA | NA | NA | NA |
| Euclid Green | 842 | 671 | −171 | −20% | NA | NA | NA | NA | NA | NA |
| Fairfax | 1,052 | 886 | −166 | −16% | NA | NA | NA | NA | NA | NA |
| Glenville | 5,561 | 4,386 | −1,175 | −21% | NA | NA | NA | NA | NA | NA |
| Goodrich-Kirtland Park | 636 | 569 | −67 | −11% | NA | NA | NA | NA | NA | NA |
| Hopkins | 38 | 100 | 62 | 163% | NA | NA | NA | NA | NA | NA |
| Hough | 1,880 | 1,662 | −218 | −12% | NA | NA | NA | NA | NA | NA |
| Jefferson | 2,111 | 2,148 | 37 | 2% | NA | NA | NA | NA | NA | NA |
| Kamms Corners | 2,283 | 2,435 | 152 | 7% | NA | NA | NA | NA | NA | NA |
| Kinsman | 1,507 | 1,095 | −412 | −27% | NA | NA | NA | NA | NA | NA |
| Lee-Harvard | 1,130 | 1,212 | 82 | 7% | NA | NA | NA | NA | NA | NA |
| Lee-Seville | 629 | 604 | −25 | −4% | NA | NA | NA | NA | NA | NA |
| Mount Pleasant | 3,198 | 2,663 | −535 | −17% | NA | NA | NA | NA | NA | NA |
| North Shore Collinwood | 1,763 | 1,907 | 144 | 8% | NA | NA | NA | NA | NA | NA |
| Ohio City | 1,107 | 1,017 | −90 | −8% | NA | NA | NA | NA | NA | NA |
| Old Brooklyn | 3,538 | 3,912 | 374 | 11% | NA | NA | NA | NA | NA | NA |
| Saint Clair-Superior | 1,715 | 1,288 | −427 | −25% | NA | NA | NA | NA | NA | NA |
| Stockyards | 1,836 | 1,839 | 3 | 0% | NA | NA | NA | NA | NA | NA |
| Tremont | 1,321 | 1,061 | −260 | −20% | NA | NA | NA | NA | NA | NA |
| Union-Miles Park | 3,412 | 3,029 | −383 | −11% | NA | NA | NA | NA | NA | NA |
| University Circle | 3,898 | 4,006 | 108 | 3% | NA | NA | NA | NA | NA | NA |
| West Boulevard | 2,857 | 3,010 | 153 | 5% | NA | NA | NA | NA | NA | NA |
| Woodland Hills | 1,416 | 990 | −426 | −30% | NA | NA | NA | NA | NA | NA |
| Total | 64,556 | 61,044 | −3,512 | −5% | 50,100 | −10,944 | −18% | 48,566 | −1,534 | −3% |
| Changing 25 to 34 yrs Population in Cleveland, 2000-2023 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Decennial and ACS censuses | ||||||||||
| 2000 | 2010 | Δ | % | 2020 | Δ | % | 2023 | Δ | % | |
| Bellaire-Puritas | 2,250 | 1,733 | −517 | −23% | NA | NA | NA | NA | NA | NA |
| Broadway-Slavic Village | 4,712 | 2,986 | −1,726 | −37% | NA | NA | NA | NA | NA | NA |
| Brooklyn Centre | 1,624 | 1,204 | −420 | −26% | NA | NA | NA | NA | NA | NA |
| Buckeye Shaker | 2,685 | 1,665 | −1,020 | −38% | NA | NA | NA | NA | NA | NA |
| Central | 1,342 | 1,653 | 311 | 23% | NA | NA | NA | NA | NA | NA |
| Clark Fulton | 1,609 | 1,165 | −444 | −28% | NA | NA | NA | NA | NA | NA |
| Collinwood Nottingham | 2,343 | 1,383 | −960 | −41% | NA | NA | NA | NA | NA | NA |
| Cudell | 1,936 | 1,372 | −564 | −29% | NA | NA | NA | NA | NA | NA |
| Cuyahoga Valley | 357 | 375 | 18 | 5% | NA | NA | NA | NA | NA | NA |
| Detroit-Shoreway | 2,159 | 1,717 | −442 | −20% | NA | NA | NA | NA | NA | NA |
| Downtown | 1,782 | 3,109 | 1,327 | 74% | NA | NA | NA | NA | NA | NA |
| Edgewater | 1,694 | 1,300 | −394 | −23% | NA | NA | NA | NA | NA | NA |
| Euclid Green | 808 | 602 | −206 | −25% | NA | NA | NA | NA | NA | NA |
| Fairfax | 863 | 597 | −266 | −31% | NA | NA | NA | NA | NA | NA |
| Glenville | 4,635 | 2,934 | −1,701 | −37% | NA | NA | NA | NA | NA | NA |
| Goodrich-Kirtland Park | 789 | 596 | −193 | −24% | NA | NA | NA | NA | NA | NA |
| Hopkins | 46 | 109 | 63 | 137% | NA | NA | NA | NA | NA | NA |
| Hough | 1,627 | 1,208 | −419 | −26% | NA | NA | NA | NA | NA | NA |
| Jefferson | 3,132 | 2,299 | −833 | −27% | NA | NA | NA | NA | NA | NA |
| Kamms Corners | 4,340 | 3,600 | −740 | −17% | NA | NA | NA | NA | NA | NA |
| Kinsman | 1,267 | 810 | −457 | −36% | NA | NA | NA | NA | NA | NA |
| Lee-Harvard | 1,093 | 827 | −266 | −24% | NA | NA | NA | NA | NA | NA |
| Lee-Seville | 575 | 417 | −158 | −27% | NA | NA | NA | NA | NA | NA |
| Mount Pleasant | 2,989 | 1,834 | −1,155 | −39% | NA | NA | NA | NA | NA | NA |
| North Shore Collinwood | 2,871 | 1,606 | −1,265 | −44% | NA | NA | NA | NA | NA | NA |
| Ohio City | 1,499 | 1,681 | 182 | 12% | NA | NA | NA | NA | NA | NA |
| Old Brooklyn | 6,266 | 4,498 | −1,768 | −28% | NA | NA | NA | NA | NA | NA |
| Saint Clair-Superior | 1,536 | 758 | −778 | −51% | NA | NA | NA | NA | NA | NA |
| Stockyards | 1,804 | 1,392 | −412 | −23% | NA | NA | NA | NA | NA | NA |
| Tremont | 1,660 | 1,822 | 162 | 10% | NA | NA | NA | NA | NA | NA |
| Union-Miles Park | 3,169 | 1,909 | −1,260 | −40% | NA | NA | NA | NA | NA | NA |
| University Circle | 1,463 | 1,134 | −329 | −22% | NA | NA | NA | NA | NA | NA |
| West Boulevard | 3,422 | 2,715 | −707 | −21% | NA | NA | NA | NA | NA | NA |
| Woodland Hills | 1,280 | 841 | −439 | −34% | NA | NA | NA | NA | NA | NA |
| Total | 71,847 | 53,996 | −17,851 | −25% | 62,334 | 8,338 | 15% | 63,832 | 1,498 | 2% |
| Changing 35 to 44 yrs Population in Cleveland, 2000-2023 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Decennial and ACS censuses | ||||||||||
| 2000 | 2010 | Δ | % | 2020 | Δ | % | 2023 | Δ | % | |
| Bellaire-Puritas | 2,459 | 1,827 | −632 | −26% | NA | NA | NA | NA | NA | NA |
| Broadway-Slavic Village | 4,897 | 2,829 | −2,068 | −42% | NA | NA | NA | NA | NA | NA |
| Brooklyn Centre | 1,670 | 1,169 | −501 | −30% | NA | NA | NA | NA | NA | NA |
| Buckeye Shaker | 2,510 | 1,526 | −984 | −39% | NA | NA | NA | NA | NA | NA |
| Central | 1,355 | 957 | −398 | −29% | NA | NA | NA | NA | NA | NA |
| Clark Fulton | 1,676 | 1,113 | −563 | −34% | NA | NA | NA | NA | NA | NA |
| Collinwood Nottingham | 2,489 | 1,404 | −1,085 | −44% | NA | NA | NA | NA | NA | NA |
| Cudell | 1,643 | 1,280 | −363 | −22% | NA | NA | NA | NA | NA | NA |
| Cuyahoga Valley | 323 | 173 | −150 | −46% | NA | NA | NA | NA | NA | NA |
| Detroit-Shoreway | 2,105 | 1,573 | −532 | −25% | NA | NA | NA | NA | NA | NA |
| Downtown | 1,182 | 1,181 | −1 | −0% | NA | NA | NA | NA | NA | NA |
| Edgewater | 1,115 | 920 | −195 | −17% | NA | NA | NA | NA | NA | NA |
| Euclid Green | 1,027 | 557 | −470 | −46% | NA | NA | NA | NA | NA | NA |
| Fairfax | 1,137 | 637 | −500 | −44% | NA | NA | NA | NA | NA | NA |
| Glenville | 5,670 | 2,859 | −2,811 | −50% | NA | NA | NA | NA | NA | NA |
| Goodrich-Kirtland Park | 672 | 537 | −135 | −20% | NA | NA | NA | NA | NA | NA |
| Hopkins | 60 | 78 | 18 | 30% | NA | NA | NA | NA | NA | NA |
| Hough | 2,222 | 1,192 | −1,030 | −46% | NA | NA | NA | NA | NA | NA |
| Jefferson | 3,362 | 2,495 | −867 | −26% | NA | NA | NA | NA | NA | NA |
| Kamms Corners | 4,435 | 3,584 | −851 | −19% | NA | NA | NA | NA | NA | NA |
| Kinsman | 1,246 | 718 | −528 | −42% | NA | NA | NA | NA | NA | NA |
| Lee-Harvard | 1,557 | 1,119 | −438 | −28% | NA | NA | NA | NA | NA | NA |
| Lee-Seville | 785 | 524 | −261 | −33% | NA | NA | NA | NA | NA | NA |
| Mount Pleasant | 3,488 | 1,995 | −1,493 | −43% | NA | NA | NA | NA | NA | NA |
| North Shore Collinwood | 3,156 | 2,102 | −1,054 | −33% | NA | NA | NA | NA | NA | NA |
| Ohio City | 1,408 | 1,105 | −303 | −22% | NA | NA | NA | NA | NA | NA |
| Old Brooklyn | 5,845 | 4,779 | −1,066 | −18% | NA | NA | NA | NA | NA | NA |
| Saint Clair-Superior | 1,722 | 816 | −906 | −53% | NA | NA | NA | NA | NA | NA |
| Stockyards | 1,776 | 1,334 | −442 | −25% | NA | NA | NA | NA | NA | NA |
| Tremont | 1,413 | 1,084 | −329 | −23% | NA | NA | NA | NA | NA | NA |
| Union-Miles Park | 3,878 | 2,173 | −1,705 | −44% | NA | NA | NA | NA | NA | NA |
| University Circle | 651 | 368 | −283 | −43% | NA | NA | NA | NA | NA | NA |
| West Boulevard | 3,435 | 2,637 | −798 | −23% | NA | NA | NA | NA | NA | NA |
| Woodland Hills | 1,258 | 745 | −513 | −41% | NA | NA | NA | NA | NA | NA |
| Total | 73,822 | 49,555 | −24,267 | −33% | 43,901 | −5,654 | −11% | 44,705 | 804 | 2% |
| Changing 45 to 54 yrs Population in Cleveland, 2000-2023 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Decennial and ACS censuses | ||||||||||
| 2000 | 2010 | Δ | % | 2020 | Δ | % | 2023 | Δ | % | |
| Bellaire-Puritas | 1,829 | 2,251 | 422 | 23% | NA | NA | NA | NA | NA | NA |
| Broadway-Slavic Village | 3,355 | 3,430 | 75 | 2% | NA | NA | NA | NA | NA | NA |
| Brooklyn Centre | 1,200 | 1,354 | 154 | 13% | NA | NA | NA | NA | NA | NA |
| Buckeye Shaker | 2,097 | 2,028 | −69 | −3% | NA | NA | NA | NA | NA | NA |
| Central | 960 | 1,233 | 273 | 28% | NA | NA | NA | NA | NA | NA |
| Clark Fulton | 1,074 | 1,178 | 104 | 10% | NA | NA | NA | NA | NA | NA |
| Collinwood Nottingham | 1,749 | 1,797 | 48 | 3% | NA | NA | NA | NA | NA | NA |
| Cudell | 1,254 | 1,372 | 118 | 9% | NA | NA | NA | NA | NA | NA |
| Cuyahoga Valley | 169 | 169 | 0 | 0% | NA | NA | NA | NA | NA | NA |
| Detroit-Shoreway | 1,610 | 1,697 | 87 | 5% | NA | NA | NA | NA | NA | NA |
| Downtown | 714 | 1,241 | 527 | 74% | NA | NA | NA | NA | NA | NA |
| Edgewater | 739 | 904 | 165 | 22% | NA | NA | NA | NA | NA | NA |
| Euclid Green | 959 | 796 | −163 | −17% | NA | NA | NA | NA | NA | NA |
| Fairfax | 984 | 914 | −70 | −7% | NA | NA | NA | NA | NA | NA |
| Glenville | 4,442 | 4,071 | −371 | −8% | NA | NA | NA | NA | NA | NA |
| Goodrich-Kirtland Park | 589 | 744 | 155 | 26% | NA | NA | NA | NA | NA | NA |
| Hopkins | 41 | 88 | 47 | 115% | NA | NA | NA | NA | NA | NA |
| Hough | 1,689 | 1,806 | 117 | 7% | NA | NA | NA | NA | NA | NA |
| Jefferson | 2,246 | 2,721 | 475 | 21% | NA | NA | NA | NA | NA | NA |
| Kamms Corners | 3,216 | 3,856 | 640 | 20% | NA | NA | NA | NA | NA | NA |
| Kinsman | 1,034 | 928 | −106 | −10% | NA | NA | NA | NA | NA | NA |
| Lee-Harvard | 1,495 | 1,547 | 52 | 3% | NA | NA | NA | NA | NA | NA |
| Lee-Seville | 671 | 657 | −14 | −2% | NA | NA | NA | NA | NA | NA |
| Mount Pleasant | 2,820 | 2,586 | −234 | −8% | NA | NA | NA | NA | NA | NA |
| North Shore Collinwood | 2,297 | 2,764 | 467 | 20% | NA | NA | NA | NA | NA | NA |
| Ohio City | 1,238 | 1,239 | 1 | 0% | NA | NA | NA | NA | NA | NA |
| Old Brooklyn | 4,160 | 5,245 | 1,085 | 26% | NA | NA | NA | NA | NA | NA |
| Saint Clair-Superior | 1,155 | 1,157 | 2 | 0% | NA | NA | NA | NA | NA | NA |
| Stockyards | 1,241 | 1,414 | 173 | 14% | NA | NA | NA | NA | NA | NA |
| Tremont | 1,039 | 1,213 | 174 | 17% | NA | NA | NA | NA | NA | NA |
| Union-Miles Park | 3,044 | 2,864 | −180 | −6% | NA | NA | NA | NA | NA | NA |
| University Circle | 608 | 510 | −98 | −16% | NA | NA | NA | NA | NA | NA |
| West Boulevard | 2,318 | 2,744 | 426 | 18% | NA | NA | NA | NA | NA | NA |
| Woodland Hills | 915 | 998 | 83 | 9% | NA | NA | NA | NA | NA | NA |
| Total | 55,111 | 59,726 | 4,615 | 8% | 42,857 | −16,869 | −28% | 41,195 | −1,662 | −4% |
| Changing 55 to 64 yrs Population in Cleveland, 2000-2023 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Decennial and ACS censuses | ||||||||||
| 2000 | 2010 | Δ | % | 2020 | Δ | % | 2023 | Δ | % | |
| Bellaire-Puritas | 1,211 | 1,544 | 333 | 27% | NA | NA | NA | NA | NA | NA |
| Broadway-Slavic Village | 2,165 | 2,348 | 183 | 8% | NA | NA | NA | NA | NA | NA |
| Brooklyn Centre | 712 | 916 | 204 | 29% | NA | NA | NA | NA | NA | NA |
| Buckeye Shaker | 1,206 | 1,695 | 489 | 41% | NA | NA | NA | NA | NA | NA |
| Central | 622 | 933 | 311 | 50% | NA | NA | NA | NA | NA | NA |
| Clark Fulton | 670 | 772 | 102 | 15% | NA | NA | NA | NA | NA | NA |
| Collinwood Nottingham | 1,107 | 1,254 | 147 | 13% | NA | NA | NA | NA | NA | NA |
| Cudell | 697 | 931 | 234 | 34% | NA | NA | NA | NA | NA | NA |
| Cuyahoga Valley | 55 | 81 | 26 | 47% | NA | NA | NA | NA | NA | NA |
| Detroit-Shoreway | 966 | 1,226 | 260 | 27% | NA | NA | NA | NA | NA | NA |
| Downtown | 354 | 727 | 373 | 105% | NA | NA | NA | NA | NA | NA |
| Edgewater | 419 | 656 | 237 | 57% | NA | NA | NA | NA | NA | NA |
| Euclid Green | 490 | 715 | 225 | 46% | NA | NA | NA | NA | NA | NA |
| Fairfax | 745 | 804 | 59 | 8% | NA | NA | NA | NA | NA | NA |
| Glenville | 2,897 | 3,175 | 278 | 10% | NA | NA | NA | NA | NA | NA |
| Goodrich-Kirtland Park | 388 | 619 | 231 | 60% | NA | NA | NA | NA | NA | NA |
| Hopkins | 48 | 67 | 19 | 40% | NA | NA | NA | NA | NA | NA |
| Hough | 1,107 | 1,412 | 305 | 28% | NA | NA | NA | NA | NA | NA |
| Jefferson | 1,310 | 1,815 | 505 | 39% | NA | NA | NA | NA | NA | NA |
| Kamms Corners | 2,080 | 2,941 | 861 | 41% | NA | NA | NA | NA | NA | NA |
| Kinsman | 769 | 753 | −16 | −2% | NA | NA | NA | NA | NA | NA |
| Lee-Harvard | 1,405 | 1,376 | −29 | −2% | NA | NA | NA | NA | NA | NA |
| Lee-Seville | 614 | 553 | −61 | −10% | NA | NA | NA | NA | NA | NA |
| Mount Pleasant | 1,834 | 2,106 | 272 | 15% | NA | NA | NA | NA | NA | NA |
| North Shore Collinwood | 1,380 | 2,370 | 990 | 72% | NA | NA | NA | NA | NA | NA |
| Ohio City | 673 | 1,166 | 493 | 73% | NA | NA | NA | NA | NA | NA |
| Old Brooklyn | 2,698 | 3,765 | 1,067 | 40% | NA | NA | NA | NA | NA | NA |
| Saint Clair-Superior | 740 | 729 | −11 | −1% | NA | NA | NA | NA | NA | NA |
| Stockyards | 888 | 859 | −29 | −3% | NA | NA | NA | NA | NA | NA |
| Tremont | 614 | 803 | 189 | 31% | NA | NA | NA | NA | NA | NA |
| Union-Miles Park | 2,506 | 2,277 | −229 | −9% | NA | NA | NA | NA | NA | NA |
| University Circle | 500 | 522 | 22 | 4% | NA | NA | NA | NA | NA | NA |
| West Boulevard | 1,400 | 1,841 | 441 | 32% | NA | NA | NA | NA | NA | NA |
| Woodland Hills | 631 | 725 | 94 | 15% | NA | NA | NA | NA | NA | NA |
| Total | 35,987 | 44,700 | 8,713 | 24% | 51,614 | 6,914 | 15% | 49,383 | −2,231 | −4% |
| Changing 65+ yr Population in Cleveland, 2000-2023 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Decennial and ACS censuses | ||||||||||
| 2000 | 2010 | Δ | % | 2020 | Δ | % | 2023 | Δ | % | |
Show the code
my_split_gt <- function(x, .rpt_group, .var_name, .var_val, .spanner, .title, .year) {
x |>
filter(rpt_group == .rpt_group) |>
mutate(geo = if_else(!!ensym(.var_name) == .var_val, "MAIN", "Other")) |>
mutate(.by = geo, pct = value / sum(value)) |>
as_tibble() |>
summarize(.by = c(geo, rpt_level), across(c(value, pct), sum)) |>
pivot_wider(names_from = geo, values_from = c(value, pct)) |>
arrange(rpt_level) |>
mutate(
rpt_level = fct_drop(rpt_level),
value_Total = value_MAIN + value_Other,
pct_Total = value_Total / sum(value_Total)
) |>
janitor::adorn_totals() |>
select(
rpt_level, ends_with("MAIN"), ends_with("Other"), ends_with("Total")
) |>
gt() |>
gt::cols_align("left", 1) |>
gt::fmt_number(columns = c(2, 4, 6), decimals = 0) |>
gt::fmt_percent(columns = c(3, 5, 7), decimals = 1) |>
gt::tab_spanner(.spanner, 2:3) |>
gt::tab_spanner("Other", 4:5) |>
gt::tab_spanner("Total", 6:7) |>
gt::cols_label(
rpt_level = "", starts_with("value") ~ "Est.", starts_with("pct") ~ "%"
) |>
gt::tab_header(
glue("{.title} Population, {.year}"),
glue("by {.rpt_group}")
) |>
gt::tab_options(heading.align = "left")
}Footnotes
“Opinion: Downtown Cleveland’s strategy to broaden appeal sees success”, Crains Cleveland Business. “Cleveland’s downtown population continues to surge”, Cleveland Fox 19 News.↩︎
Downtown Cleveland Inc. commissioned a report, “Downtown Cleveland Market Study Report” (pdf), by the Urban Partners consulting firm. The report was released in Apr 2023. Figures are from Table 1: 15,330 people in 2010, 18,708 people in 2020 (22% increase).↩︎
See the Downtown neighborhood (statistical processing area, SPA) in the data table.↩︎
“There’s Still No Agreement on How Many Clevelanders Actually Live Downtown”, Cleveland Scene, Sep 17, 2024.↩︎
Cleveland’s population plateaued around 1930 at 900K. The peak was 914K in the 1950 census. Between 1960 and 1980 the population declined by a third. The current population is slightly below the 1900 value. See Visual Cleveland at https://visual.clevelandhistory.org/census/.↩︎
362,670 +/- 62. https://data.census.gov/table/ACSST1Y2023.S0101?q=cleveland,%20oh↩︎
Social Planning Areas (SPAs) were developed in the 1950s to coordinate social services at the neighborhood level. Learn more at the Encyclopedia of Cleveland History. Wikipedia has a nice explanation of how neighborhoods relate to Statistical (or social) Planning Areas.↩︎
From https://data.clevelandohio.gov/, go to the Data Catalog and scroll to Census 2020 Analysis.↩︎